home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-04-27 | 4.2 KB | 121 lines | [TEXT/????] |
- ;;; $Header: pfe.scm,v 1.5 88/07/18 22:46:59 GMT hal Exp $
- ;;;; Partial-fractions expansions
-
- (if-mit
- (declare (usual-integrations = + - * /
- zero? 1+ -1+
- ;; truncate round floor ceiling
- sqrt exp log sin cos)))
- (define (rat-func->pfe ratfunc)
- (numer-poles->pfe (car ratfunc)
- (sort (poly->roots (cadr ratfunc))
- (lambda (z1 z2)
- (< (magnitude z1) (magnitude z2))))))
-
- (define (pfe->rat-func pfe)
- (let ((residues (car pfe)) (poles (cadr pfe)))
- (let ((np (pfe->numer-poles residues poles)))
- (list (car np) (roots->poly poles)))))
-
-
- ;;; The following partial-fraction procedure returns a list of two terms
- ;;; -- (residue-list pole-list) given a list of numer-poly coefficients
- ;;; and the denominator pole-list. For best accuracy, denominator roots
- ;;; should be entered in increasing order. Repeated roots must be
- ;;; clustered together. As an example consider
- ;;;
- ;;; 2x^5 + 9x^4 - x^3 - 26x^2 + 5x - 1
- ;;; ----------------------------------
- ;;; (x + 1)^2 (x - 1)^3 (x + 2)
- ;;;
- ;;; 3 -2 -1 1 3 1
- ;;; = ------- + --- + ------- + ------- + --- + ---
- ;;; (x+1)^2 x+1 (x-1)^3 (x-1)^2 x-1 x+2
- ;;;
- ;;; (numer-poles->pfe '(-1 5 -26 -1 9 2) '(-1 -1 1 1 1 -2))
- ;;; ==> ((3 -2 -1 1 3 1) (-1 -1 1 1 1 -2))
-
- (define (numer-poles->pfe numer-poles)
- (let ((numer-poly (car numer-poles))
- (pole-list (cadr numer-poles)))
- (define (pfe-iter poly poles)
- (if (null? poles)
- '()
- (let ((den (other-roots->poly (cdr poles) (car poles))))
- (let ((coef (/ (poly-value poly (car poles))
- (poly-value den (car poles)))))
- (cons coef
- (pfe-iter
- (car
- (div-polys
- (sub-polys poly (scale-poly coef den))
- (list (- (car poles)) 1)))
- (cdr poles)))))))
- (define (other-roots->poly root-list root)
- (if (member root root-list)
- (other-roots->poly (cdr root-list) root)
- (roots->poly root-list)))
- (list (pfe-iter numer-poly pole-list) pole-list)))
-
- ;;; The following procedure reconstructs a rat-func in the form
- ;;; (numer-poly pole-list) from a partial-fraction expansion in the
- ;;; form (residue-list pole-list). Example
- ;;;
- ;;; (pfe->numer-poles '((3 -2 -1 1 3 1) (-1 -1 1 1 1 -2)))
- ;;; ==> ((-1 5 -26 -1 9 2) (-1 -1 1 1 1 -2))
-
- (define (pfe->numer-poles pfe)
- (let ((residue-list (car pfe)) (pole-list (cadr pfe)))
- (define (iter residues poles pending-poles)
- (if (null? residues)
- '()
- (add-polys (scale-poly (car residues) (roots->poly (cdr poles)))
- (if (member (car poles) (cdr poles))
- (iter (cdr residues)
- (cdr poles)
- (cons (car poles) pending-poles))
- (iter (cdr residues)
- (append (cdr poles)
- (cons (car poles) pending-poles))
- '())))))
- (list (iter (reverse residue-list) (reverse pole-list) '()) pole-list)))
-
- ;;; The following procedure returns a function of a real variable, t,
- ;;; whose value is the Inverse Laplace Transform of a rational function
- ;;; described by a RESIDUE-LIST of residues and a POLE-LIST of poles, as
- ;;; might be returned by RAT-FUNC->PFE above.
-
- (define (pfe->time pfe)
- (define (rptd-pole-residues poly residue-list pole-list)
- ((if (or (null? (cdr residue-list))
- (not (= (car pole-list) (cadr pole-list))))
- list
- rptd-pole-residues)
- (cons (car residue-list) poly)
- (cdr residue-list)
- (cdr pole-list)))
- (define (insert-factorials lst n)
- (if (null? lst)
- '()
- (cons (car lst)
- (map (lambda (x) (/ x n))
- (insert-factorials (cdr lst) (1+ n))))))
- (let loop ((residue-list (car pfe)) (pole-list (cadr pfe)))
- (if (null? residue-list)
- 0
- (let ((proc
- (lambda (t)
- (if (negative? t)
- 0
- (exp (* (car pole-list) t))))))
- (if (or (null? (cdr residue-list))
- (not (= (car pole-list) (cadr pole-list))))
- (+ (* (car residue-list) proc)
- (loop (cdr residue-list) (cdr pole-list)))
- (let ((new-lists (rptd-pole-residues (list (car residue-list))
- (cdr residue-list)
- (cdr pole-list))))
- (+ (* (poly->procedure (insert-factorials (car new-lists) 1))
- proc)
- (loop (cadr new-lists) (caddr new-lists)))))))))
-